package com.pojoin.system.service.impl;

import com.pojoin.system.dao.CurrencyHistoryDao;
import com.pojoin.system.dao.GradeDao;
import com.pojoin.system.dao.OrderDao;
import com.pojoin.system.dao.UserDao;
import com.pojoin.system.domain.CurrencyHistoryDO;
import com.pojoin.system.domain.GradeDO;
import com.pojoin.system.domain.OrderDO;
import com.pojoin.system.domain.UserDO;
import com.pojoin.system.domain.vo.User;
import com.pojoin.system.domain.vo.UserGradeVo;
import com.pojoin.system.service.FinanceService;
import com.pojoin.system.service.MoneyHistoryService;
import com.pojoin.system.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @version 2.0.0
 * @auther liyangzhu
 * @since 2.0.0 2020/6/29
 */
@Slf4j
@Service
public class FinanceServiceImpl implements FinanceService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    OrderDao orderDao;
    @Autowired
    UserDao userDao;
    @Autowired
    GradeDao gradeDao;
    @Autowired
    CurrencyHistoryDao currencyHistoryDao;

    @Autowired
    OrderService orderService;


    @Autowired
    MoneyHistoryService moneyHistoryService;

    @Override
    public int save(OrderDO orderDO) {
        return orderDao.save(orderDO);
    }

    @Override
    public List<OrderDO> list(Map<String, Object> map) {
        return orderDao.list(map);
    }

    @Override
    public int count(Map<String, Object> map) {
        return orderDao.count(map);
    }

    @Override
    public void core(UserDO newUser, UserDO inviteUser, UserDO baoDan, Long userId, Double money) {
        // 0. 初始化数据
        //判断邀请人的级别
        String inviteGrade = inviteUser.getGrade();
        List<UserDO> inviteList = userDao.listInvite(inviteUser.getParentLink());
        GradeDO gradeDO = gradeDao.getByGrade(inviteGrade);
        if (gradeDO == null) {
            gradeDO = new GradeDO();
            gradeDO.setProportion(0d);
        }

        // 1. 报单 代理有5%
        Double award = money * 0.05;
        UserDO coreuser = baoDan;
        saveMoney(0d, award, 0d, 0d, coreuser, newUser);
        // 2. 邀请人推荐奖 15%
        Double recommend = money * 0.15;
        saveMoney(recommend, 0.00, 0.00, 0.00, inviteUser, newUser);

        // 4. 星级奖励 动态计算 给每个人分配星级差奖励
        String parentLink = inviteUser.getParentLink();
        parentLink = parentLink + "," + inviteUser.getUserId();
        parentLink = parentLink + "," + newUser.getUserId();
        distributeStarProfile(newUser, inviteUser, money, parentLink);


        // 3. 所有的合伙人，分 5%
        // 5. 代数
        saveProfit(inviteList, gradeDO, money, newUser);

        orderService.merge(newUser);
    }

    private void distributeStarProfile(UserDO newUser, UserDO inviteUser, Double money, String parentLink) {
        boolean b = parentLink.startsWith("0");
        if (b){
            parentLink = parentLink.substring(2, parentLink.length());
        }
        List<User> inviteList = userDao.listInvite2(parentLink);
        // 这里只是计算父级 星级差
        for (User user: inviteList){
            if (user == null) continue;
            Long userId = user.getUserId();
            // 1. 查询用户星级
            log.info("查询用户星级 {} {} {}", userId,user.getGrade(),user.getParentId());
            // 查询用户百分比
            GradeDO byGrade = gradeDao.getByGrade(user.getGrade());
            if (byGrade == null) {
                continue;
            }
            Double proportion = byGrade.getProportion();
            // 2. 查询用户父亲星级及百分比
            UserGradeVo userGradeVo = userDao.selectUserGradeByUserId(user.getParentId());
            if (userGradeVo != null){
                Double parentProportion = userGradeVo.getProportion();
                log.info("查询用户父亲星级及百分比 {} {}",userGradeVo.getGrade(),userGradeVo.getProportion());

                if (userGradeVo.getProportion() != null) {
                    if (user.getGrade().equals(userGradeVo.getGrade())) {
                        continue;
                    }
                    Double starReward = money*(parentProportion - proportion);
                    UserDO userDO = new UserDO();
                    // 这里是给父级 星级差
                    BeanUtils.copyProperties(userGradeVo, userDO);
                    saveMoney(0.00, 0.00, starReward, 0.00, userDO, newUser);
                }

            }


        }


    }

    /**
     * 获取星级差
     *
     * @param gradName 上一级
     * @param next     下一级
     * @return
     */
    Double getRange(String gradName, String next) {
        return gradeDao.getByGrade(gradName).getProportion() - gradeDao.getByGrade(next).getProportion();
    }

    /**
     * 保存合伙人和懂事个子分红的5%
     * 保存一二代收益
     *
     * @param inviteList 邀请人的所有上级人员
     * @param gradeDO    邀请人的级别
     * @Param UserDO 新加入的人
     */
    public void saveProfit(List<UserDO> inviteList, GradeDO gradeDO, Double money, UserDO newUser) {
        //懂事平分5%
        //合伙人平分5%
        Map<String, Object> map = new HashMap<>(1);
        List<UserDO> listH = userDao.listH(map);
        /*List<UserDO> listD = userDao.listD();
        if (null != listD && listD.size() > 0) {
            for (UserDO userDO : listD) {
                Double partnerMoney = money * 0.05 / listD.size();
                saveMoney2(partnerMoney, userDO, newUser);
            }
        }*/
        if (null != listH && listH.size() > 0) {
            for (UserDO userDO : listH) {
                Double partnerMoney = money * 0.05 / listH.size();
                saveMoney2(partnerMoney, userDO, newUser);
            }
        }

        //计算一二代收益
        getProfit(inviteList, gradeDO, money, newUser);
    }


    /**
     * 计算一二代收益
     *
     * @param inviteList
     * @param gradeDO
     * @param money
     * @param newUser
     */
    public void getProfit(List<UserDO> inviteList, GradeDO gradeDO, Double money, UserDO newUser) {

        GradeDO oneGradeDO = gradeDao.getByGrade("一代");
        GradeDO twoGradeDO = gradeDao.getByGrade("二代");

        //计算一二代收益
        if (inviteList.size() > 0) {
            //一代收益 365*(0.15+0.22)*0.35
            UserDO userDO = inviteList.get(0);
            Double oneMoney = money * (0.15 + gradeDO.getProportion()) * oneGradeDO.getProportion();
            saveMoney(0d, 0d, 0d, oneMoney, userDO, newUser);
            if (inviteList.size() > 1) {
                //二代收益 365*(0.15+0.22)*0.35
                UserDO userDO1 = inviteList.get(1);
                Double twoMoney = money * (0.15 + gradeDO.getProportion()) * twoGradeDO.getProportion();
                saveMoney(0d, 0d, 0d, twoMoney, userDO1, newUser);
            }
        }

    }

    /**
     * 记录收益，修改余额
     *
     * @param recommend  推荐奖
     * @param award      报单奖
     * @param range      级差奖
     * @param profit     收益
     */
    @Override
    public void saveMoney(Double recommend, Double award, Double range, Double profit, UserDO inviteUser, UserDO newUser) {
        CurrencyHistoryDO currencyHistoryDO = new CurrencyHistoryDO();
        currencyHistoryDO.setRecommend(recommend);
        currencyHistoryDO.setAward(award);
        currencyHistoryDO.setRange(range);
        currencyHistoryDO.setProfit(profit);
        currencyHistoryDO.setBonus(0d);
        currencyHistoryDO.setUserId(inviteUser.getUserId());
        currencyHistoryDO.setFromUserId(newUser.getUserId());
        currencyHistoryDO.setFromUserName(newUser.getUsername());
        currencyHistoryDO.setCreatTime(new Date());
        currencyHistoryDO.setStatus("1");
        currencyHistoryDao.save(currencyHistoryDO);
        Double total = recommend + award + range + profit;


        userDao.updateMoney(total, inviteUser.getUserId());
        if (recommend > 0d) {
            UserDO toUser = userDao.get(Long.valueOf(inviteUser.getUserId()));
            moneyHistoryService.addMoney(inviteUser.getUserId(), recommend, 0d, newUser.getUserId(), "推荐奖", "m", toUser.getMoney().toString(), toUser.getBalance().toString());
            logger.info("=====用户：" + inviteUser.getUserId() + "得到推荐奖：" + recommend + "元，" + "来自用户：" + newUser.getUserId() + "注册");
        }
        if (award > 0d) {
            UserDO toUser = userDao.get(Long.valueOf(inviteUser.getUserId()));
            moneyHistoryService.addMoney(inviteUser.getUserId(), award, 0d, newUser.getUserId(), "报单奖", "m", toUser.getMoney().toString(), toUser.getBalance().toString());

            logger.info("=====用户：" + inviteUser.getUserId() + "得到报单奖：" + award + "元，" + "来自用户：" + newUser.getUserId() + "注册");
        }
        if (range > 0d) {
            UserDO toUser = userDao.get(Long.valueOf(inviteUser.getUserId()));
            moneyHistoryService.addMoney(inviteUser.getUserId(), range, 0d, newUser.getUserId(), "极差奖", "m", toUser.getMoney().toString(), toUser.getBalance().toString());

            logger.info("=====用户：" + inviteUser.getUserId() + "得到级差奖：" + range + "元，" + "来自用户：" + newUser.getUserId() + "注册");
        }
        if (profit > 0d) {
            UserDO toUser = userDao.get(Long.valueOf(inviteUser.getUserId()));
            moneyHistoryService.addMoney(inviteUser.getUserId(), profit, 0d, newUser.getUserId(), "收益", "m", toUser.getMoney().toString(), toUser.getBalance().toString());

            logger.info("=====用户：" + inviteUser.getUserId() + "得到收益：" + profit + "元，" + "来自用户：" + newUser.getUserId() + "注册");
        }
    }

    /**
     * 记录分红，修改余额
     *
     * @param bonus      分红
     */
    public void saveMoney2(Double bonus, UserDO inviteUser, UserDO newUser) {
        CurrencyHistoryDO currencyHistoryDO = new CurrencyHistoryDO();
        currencyHistoryDO.setRecommend(0d);
        currencyHistoryDO.setAward(0d);
        currencyHistoryDO.setRange(0d);
        currencyHistoryDO.setProfit(0d);
        currencyHistoryDO.setBonus(bonus);
        currencyHistoryDO.setUserId(inviteUser.getUserId());
        currencyHistoryDO.setFromUserId(newUser.getUserId());
        currencyHistoryDO.setFromUserName(newUser.getUsername());
        currencyHistoryDO.setCreatTime(new Date());
        currencyHistoryDO.setStatus("1");
        currencyHistoryDao.save(currencyHistoryDO);

        userDao.updateMoney(bonus, inviteUser.getUserId());
        if (bonus > 0d) {
            UserDO toUser = userDao.get(Long.valueOf(inviteUser.getUserId()));
            moneyHistoryService.addMoney(inviteUser.getUserId(), bonus, 0d, newUser.getUserId(), "分红", "m", toUser.getMoney().toString(), toUser.getBalance().toString());

            logger.info("=====用户：" + inviteUser.getUserId() + "得到分红：" + bonus + "元，" + "来自用户：" + newUser.getUserId() + "注册");
        }
    }


}
